package com.yjhh.scala

/**
  *
  * 函数式编程进阶
  * 1.函数和变量一样可以作为Scala语言的一等公民，函数可以直接赋值给变量
  * 2.函数更常用到的方式是匿名函数，定义的时候只需要说明输入参数的类型和函数体即可，不需要名称，但是如果你要使用的话，
  * 一般把这个匿名函数赋值给一个变量（其实是val常量），Spark源码中大量处在这种语法，必须掌握。
  * 3.函数可以作为参数直接传递给函数 ，这极大的简化了编程的语法，这是样的原有：
  * 第一：以前JAva的方式是new一个接口实例，并且在接口实例的回调方法callback中来实现业务逻辑，现在是直接把回调的方法
  * callback传递给我们的函数，且在函数体中直接使用，提升了开发的效率
  * 第二：这种方式非常的方便编写负责的业务逻辑和控制逻辑，对于图计算、机器学习、深度学习等而言至关重要
  *
  * 函数作为函数的参数传递的编程方式是称之为高阶函数的编程方式，Spark中有60%都是这样的代码
  * 4.函数式编程一个强大的地方之一在于函数的返回值可以是函数，当函数的返回类型是函数的时候，这个时候就表明scala的函数实现了闭包
  * Scala闭包的内幕是：Scala的函数背后是类和对象，所以Scala的参数都作为了对象的成员！！！！！！，所以后续可以据需访问，这就是Scala实现闭包的原理内幕
  *
  * 5.Curying，复杂的函数式编程中经常使用，可以维护变量在内存中的状态，且实现返回函数的链式功能，可以实现非常复杂的算法和逻辑
  */
object FunctionProgramming {

  def main(args: Array[String]): Unit = {
    //1
    val hiData = hiBigData _
    hiData("Spark")

    //2
    val f = (name: String) => println("Hi," + name)
    f("Kafka")

    //3
    def getName(func: (String) => Unit, name: String): Unit = {
      func(name)
    }

    getName(f, "Scala")

    println(Array(1 to 10: _*).map(item => item * 2).foreach(data => print(data + "  ")))

    /**
      *4.函数式编程一个强大的地方之一在于函数的返回值可以是函数，当函数的返回类型是函数的时候，这个时候就表明scala的函数实现了闭包
      * Scala闭包的内幕是：Scala的函数背后是类和对象，所以Scala的参数都作为了对象的成员！！！！！！，所以后续可以据需访问，这就是Scala实现闭包的原理内幕
      */
    def funcResult1 = (name: String) => println("   " + name)
    funcResult1("Hello")

    val funcval = funcResult1;     //函数赋值给变量
    funcval("test")

    def funcResult(message: String) = (name: String) => println(message + "   " + name)

    funcResult("Hello")("Java") //Currying 克里化，函数写法

    val result = funcResult("Hello")
    result("Java")
  }

  def hiBigData(name: String): Unit = {
    println("Hi," + name)
  }

}
